package org.bluedream.core.module.sys.service;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.bluedream.comm.base.BaseServiceImpl;
import org.bluedream.comm.utils.CreateGUIDUtil;
import org.bluedream.comm.utils.ListUtils;
import org.bluedream.core.module.sys.entity.*;
import org.bluedream.core.module.sys.dao.RoleDao;
import org.bluedream.comm.utils.EmptyUtil;
import org.bluedream.comm.utils.StringUtils;
import org.bluedream.core.module.sys.entity.org.OrgRelation;
import org.bluedream.core.module.sys.service.org.OrgRelationService;
import org.bluedream.core.utils.UserUtil;
import org.bluedream.core.utils.YmlRead;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.*;

@Service
@DS("master")
@Transactional(
        readOnly = true
)
public class RoleService extends BaseServiceImpl<RoleDao, Role> implements IService<Role> {
    private static final Logger logger = LoggerFactory.getLogger(RoleService.class);

    @Resource
    private MenuService menuService;

    @Resource
    private OrganizationService organizationService;

    @Resource
    private OrgRelationService orgRelationService;

    @Resource
    private RoleRelationService roleRelationService;

    public Role isSystemRole(String loginCode){
        return baseMapper.isSystemRole(loginCode , YmlRead.getValueToString("superManagerRole"));
    }

    public IPage<Role> findPage( Role entity, String... args) {
        Map<String , Object> search = null;
        if (!UserUtil.isSystem()){
            search = new HashMap<>();
            search.put("a.org_id;eq" , UserUtil.getLoginOrgCode());
        }
        if (EmptyUtil.isNoEmpty(entity.getRoleName())
        ){
            search = new HashMap<>();
            search.put("a.ROLE_NAME;eq" , entity.getRoleName());
        }else {
            long limit = entity.getLimit();
            long page = entity.getPage();
            entity = new Role();
            entity.setLimit(limit);
            entity.setPage(page);
        }
        return super.findPage(entity , search , args);
    }

    /**
     * 获取树结构数据
     * @return
     */
    public List<Map<String , Object>> treeData(){
        List<Map<String , Object>> mapList = new ArrayList<>();
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>(new Role());
        queryWrapper.orderByAsc("ROLE_SORT" );
        List<Role> list = super.list(queryWrapper);
        for (Role c1:list
        ) {
            if (!Role.STATUS_NORMAL.equals(c1.getStatus())){
                continue;
            }

            Map<String , Object> map = new HashMap<>();
            map.put("id" , c1.getId());
            map.put("pId" , "0");
            map.put("name" , StringUtils.getTreeNodeName("1" , c1.getRoleCode() , c1.getRoleName()));
            mapList.add(map);
        }
        return mapList;
    }

    public List<Map<String , Object>> treeDataToOrg(String isShowCode , String excludeCode , Role role){
        List<Organization> isCheck = organizationService.selectListByRole(role.getId());
        List<Organization> source = organizationService.selectListByLoginOrg();
        return organizationService.treeData(excludeCode , isShowCode , source , isCheck);
    }

    public List<Map<String , Object>> treeDataToMenu(String isShowCode , String excludeCode , Role role){
        List<Menu> isCheck = menuService.getMenusByRole(role.getId());
        List<Menu> source = menuService.getMenusByLoginUserAndLoginOrg();
        return menuService.treeData(excludeCode , isShowCode , source , isCheck);
    }

    public Role createNextNode(Role entity){
        try {
            if (entity.getIsNewRecord()) {
                entity = new Role();
                Role lastNode = this.getLastNode(entity , "role_code");
                String role_code = EmptyUtil.isEmpty(lastNode)?"001": CreateGUIDUtil.nextCode(lastNode.getRoleCode());
                entity.setRoleCode(role_code);
            }
            return entity;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public Role getLastNode(Role entity , String... orders){
        Page<Role> page = new Page<>(1,1);
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.apply("regexp_like(role_code,'^[0-9]+[0-9]$')");
        queryWrapper.orderByDesc(orders);
        IPage<Role> iPage = super.page(page , queryWrapper);
        if (EmptyUtil.isNoEmpty(iPage.getRecords())){
            return iPage.getRecords().get(0);
        }
        return null;
    }


    @Override
    public Role getById(Serializable id) {
        if (EmptyUtil.isEmpty(id)){
            return new Role();
        }
        return super.getById(id);
    }

    @Transactional(
            readOnly = false,
            rollbackFor = Exception.class
    )
    public boolean save(Role role){
        try {
            boolean flag;
            boolean isNewRecord = super.getIsNewRecord(role , "role_code" , "getRoleCode");
            role.setIsNewRecord(isNewRecord);
            flag = super.save(role);
            if (UserUtil.isSystem()){
                return flag;
            }else {
                QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("role_code" , role.getRoleCode());
                role = this.getOne(queryWrapper);
                List<String> list = new ArrayList<>();
                list.add(UserUtil.getLoginOrgCode());
                role.setIdList(list);
                return saveOrg(role);
            }
        }catch (Exception e1){
            logger.error("保存角色信息失败，错误信息：" + e1.getMessage());
            //todo:@Transactional和try catch捕获异常会让注解失效
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
    }

    @Transactional(
            readOnly = false,
            rollbackFor = Exception.class
    )
    public boolean saveOrg(Role role){
        try {
            boolean isSuccessSave = false;

            List<String> oldIds = baseMapper.getOrganizations4Id(role);
            List<String> newIds = role.getIdList();

            if (EmptyUtil.isEmpty(oldIds) && EmptyUtil.isEmpty(newIds)){
                return true;
            }

            // 1. 从原集合中删除 新集合中存在的数据
            List<String> delIds = ListUtils.getSubtract(oldIds , newIds);

            //从新集合中删除已经存在的 角色-菜单数据
            List<String> addIds = ListUtils.getSubtract(newIds , oldIds);

            if (EmptyUtil.isNoEmpty(delIds)){
                List<String> delList = new ArrayList<>();
                for (int i = 0; i < delIds.size(); i++) {
                    QueryWrapper<OrgRelation> orgRelationQueryWrapper = new QueryWrapper<>();
                    orgRelationQueryWrapper.eq("org_id" , delIds.get(i));
                    orgRelationQueryWrapper.eq("type" , "role");
                    orgRelationQueryWrapper.eq("entity_id" , role.getId());
                    delList.add(orgRelationService.getOne(orgRelationQueryWrapper).getId());
                }

                isSuccessSave = orgRelationService.removeByIds(delList);
                if (!isSuccessSave){
                    return false;
                }
            }

            if (EmptyUtil.isNoEmpty(addIds)){
                List<OrgRelation> addList = new ArrayList<>();
                for (int i = 0; i < addIds.size(); i++) {
                    addList.add(new OrgRelation(addIds.get(i) , "role" , role.getId()));
                }

                isSuccessSave = orgRelationService.saveBatch(addList);
                if (!isSuccessSave){
                    return false;
                }
            }
            return isSuccessSave;
        }catch (Exception e){
            logger.error("保存角色-组织信息失败，错误信息：" + e.getMessage());
            //todo:@Transactional和try catch捕获异常会让注解失效
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
    }

    @Transactional(
            readOnly = false,
            rollbackFor = Exception.class
    )
    public boolean saveMenu(Role role){
        try {
            boolean isSuccessSave = false;

            List<String> oldIds = baseMapper.getMenus4Id(role);

            List<String> newIds = role.getIdList();

            if (EmptyUtil.isEmpty(oldIds) && EmptyUtil.isEmpty(newIds)){
                return true;
            }

            // 1. 从原集合中删除 新集合中存在的数据
            List<String> delIds = ListUtils.getSubtract(oldIds , newIds);

            //从新集合中删除已经存在的 角色-菜单数据
            List<String> addIds = ListUtils.getSubtract(newIds , oldIds);

            if (EmptyUtil.isEmpty(delIds) && EmptyUtil.isEmpty(addIds)){
                return true;
            }

            if (EmptyUtil.isNoEmpty(delIds)){
                List<String> delRoleRelationIDs = new ArrayList<>();
                for (int i = 0; i < delIds.size(); i++) {
                    QueryWrapper<RoleRelation> roleRelationQueryWrapper = new QueryWrapper<>();
                    roleRelationQueryWrapper.eq("role_id" , role.getId());
                    roleRelationQueryWrapper.eq("type" , "menu");
                    roleRelationQueryWrapper.eq("entity_id" , delIds.get(i));
                    delRoleRelationIDs.add(roleRelationService.getOne(roleRelationQueryWrapper).getId());
                }

                isSuccessSave = roleRelationService.removeByIds(delRoleRelationIDs);
                if (!isSuccessSave){
                    return false;
                }
            }

            if (EmptyUtil.isNoEmpty(addIds)){
                List<RoleRelation> addRoleRelations = new ArrayList<>();
                for (int i = 0; i < addIds.size(); i++) {
                    addRoleRelations.add(new RoleRelation(role.getId() , "menu" , addIds.get(i)));
                }

                isSuccessSave = roleRelationService.saveBatch(addRoleRelations);
                if (!isSuccessSave){
                    return false;
                }
            }

            return isSuccessSave;
        }catch (Exception e){
            logger.error("保存角色-权限信息失败，错误信息：" + e.getMessage());
            //todo:@Transactional和try catch捕获异常会让注解失效
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
    }

    @Transactional(
            readOnly = false,
            rollbackFor = Exception.class
    )
    public boolean saveUser(Role role){
        try {
            boolean isSuccessSave = false;

            List<String> oldIds = baseMapper.getUsers4Id(role);
            List<String> newIds = role.getIdList();

            if (EmptyUtil.isEmpty(oldIds) && EmptyUtil.isEmpty(newIds)){
                return true;
            }

            // 1. 从原集合中删除 新集合中存在的数据
            List<String> delIds = ListUtils.getSubtract(oldIds , newIds);
            //从新集合中删除已经存在的 角色-菜单数据
            List<String> addIds = ListUtils.getSubtract(newIds , oldIds);

            if (EmptyUtil.isNoEmpty(delIds)){
                List<String> delList = new ArrayList<>();
                for (int i = 0; i < delIds.size(); i++) {
                    QueryWrapper<RoleRelation> roleRelationQueryWrapper = new QueryWrapper<>();
                    roleRelationQueryWrapper.eq("role_id" , role.getId());
                    roleRelationQueryWrapper.eq("type" , "user");
                    roleRelationQueryWrapper.eq("entity_id" , delIds.get(i));
                    delList.add(roleRelationService.getOne(roleRelationQueryWrapper).getId());
                }

                isSuccessSave = roleRelationService.removeByIds(delList);
                if (!isSuccessSave){
                    return false;
                }
            }

            if (EmptyUtil.isNoEmpty(addIds)){
                List<RoleRelation> addList = new ArrayList<>();
                for (int i = 0; i < addIds.size(); i++) {
                    addList.add(new RoleRelation(role.getId(), "user" , addIds.get(i) ));
                }

                isSuccessSave = roleRelationService.saveBatch(addList);
                if (!isSuccessSave){
                    return false;
                }
            }
            return isSuccessSave;
        }catch (Exception e){
            logger.error("保存角色-组织信息失败，错误信息：" + e.getMessage());
            //todo:@Transactional和try catch捕获异常会让注解失效
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
    }

}
